using UnityEngine;
using System.Collections;
using GeneralStorageClasses;

namespace MenuItems
{
	/// <summary>
	/// New game active event.
	/// </summary>
	public delegate void NewGameActiveEvent (bool active);

	/// <summary>
	/// New game.
	/// </summary>
	public class NewGame : MonoBehaviour
	{
		//Inspector variables
		public GUISkin skinForGUI;
		public GUIStyle windowStyle;

		public GUIStyle NewGameLabel;

		public AudioSource mySound;
		
		//Event handler
		public event NewGameActiveEvent NewGameStateChange;
		
		//Class variables
		private bool visible;
		private Rect windowRect;
		private float buttonPosition;
		private static NewGame m_Instance;
		private string seed;
		private string tileWidth;
		private string tileHeight;

		void Awake ()
		{
			m_Instance = this;
			visible = false;
			seed = "0.42";
			tileWidth = "5";
			tileHeight = "5";
			buttonPosition = Screen.height - Screen.height * 0.222f;
			int windowWidth = windowStyle.active.background.width;
			int windowHeight = windowStyle.active.background.height;
			windowRect = new Rect (Screen.width / 2 - windowWidth / 2, buttonPosition - windowHeight - 100, windowWidth, windowHeight);
		}

		/// <summary>
		/// Closes the new game menu.
		/// </summary>
		private void closeNewGame ()
		{
			Visible = false;
		}
		
		public void OnGUI ()
		{
			if (visible) {
				GUI.skin = skinForGUI;
				GUI.Window (4, windowRect, windowContents, "", windowStyle);
				
				if (GUI.Button (new Rect (Screen.width / 2 - 150, buttonPosition, 100, 32), "Start Game")) {
					//Give parameters to the GameManager to init the world
					GameManager.Instance.SetGameSettings (float.Parse (seed), float.Parse (tileWidth), float.Parse (tileHeight));
					Application.LoadLevel ("OverWorld");
					mySound.Play ();
				}
				if (GUI.Button (new Rect (Screen.width / 2 + 49, buttonPosition, 100, 32), "Back")) {
					closeNewGame ();
					mySound.Play ();
				}
			}
		}

		/// <summary>
		/// Displays the options labels and text box values.
		/// </summary>
		/// <param name="controlName">Control name.</param>
		/// <param name="labelName">Label name.</param>
		/// <param name="textboxstring">Textboxstring.</param>
		private void textOptions (string controlName, string labelName, ref string textboxstring)
		{
			//Layout objects 2 per line [Label][Textbox]
			GUILayoutOption width = GUILayout.MaxWidth (windowRect.width / 2);
			GUILayout.BeginHorizontal ();
			GUILayout.Label (labelName, width);
			GUI.SetNextControlName (controlName);
			textboxstring = GUILayout.TextField (textboxstring, width);
			GUILayout.EndHorizontal ();
		}

		/// <summary>
		/// Checks and clamps the settings so they can not go below or above desired amounts.
		/// </summary>
		/// <param name="controlName">Control name.</param>
		/// <param name="boxValue">Box value.</param>
		/// <param name="min">Minimum.</param>
		/// <param name="max">Max.</param>
		private void checkAndClamp (string controlName, ref string boxValue, float min, float max)
		{
			//Temp variable for tryParse out
			float temp;

			//If the GUI object is not in focus 
			if (GUI.GetNameOfFocusedControl () != controlName) {
				//Try change string to a float if success enter
				if (float.TryParse (boxValue, out temp)) {
					//Clamp down variables to only allow a min and max number
					boxValue = Mathf.Clamp (temp, min, max).ToString ();
				}
			}
		}

		/// <summary>
		/// Contains the window contents of new game settings.
		/// </summary>
		/// <param name="WindowID">Window I.</param>
		private void windowContents (int WindowID)
		{
			GUILayout.BeginVertical ();

			GUILayout.Label ("New Game", NewGameLabel, GUILayout.MinHeight (windowRect.height / 5));

			//Draw labels and textboxes for init of level
			textOptions ("TileWidth", "Width:", ref tileWidth);
			textOptions ("TileHeight", "Height:", ref tileHeight);
			textOptions ("Seed", "Seed:", ref seed);

			//Draw random button for seed
			GUILayout.BeginHorizontal ();
			GUILayout.Space (windowRect.width / 2);

			if (GUILayout.Button ("Random")) {
				seed = Random.value.ToString ();
			}
			GUILayout.EndHorizontal ();
			GUILayout.EndVertical ();

			//Fool checks and boundry checks
			checkAndClamp ("TileWidth", ref tileWidth, 5, 25);
			checkAndClamp ("TileHeight", ref tileHeight, 5, 25);
			checkAndClamp ("Seed", ref seed, 0, 1);
		}
	
		/// <summary>
		/// Gets or sets a value indicating whether this <see cref="MenuItems.NewGame"/> is visible.
		/// </summary>
		/// <value><c>true</c> if visible; otherwise, <c>false</c>.</value>
		public bool Visible {
			get {
				return visible;
			}
			set {
				//Setup Event handle on enable/disable of options
				if (NewGameStateChange != null) {
					//if not null send callback to all listeners
					NewGameStateChange (value);
				}
				this.visible = value;
			}
		}

		/// <summary>
		/// Gets the new game instance.
		/// </summary>
		/// <value>The instance.</value>
		public static NewGame Instance {
			get {
				if (m_Instance == null) {
					Debug.LogError ("NewGame: NewGame not attatched to an object.");
				}
				return m_Instance; 
			}
		}
	}
}